﻿using System.IO;
using lucere.exception;

namespace lucere.io.concurrency
{
	public class SimpleFSLock : Lock
	{
		private readonly DirectoryInfo _lockDir;
		FileInfo _lockFile;
		public SimpleFSLock(DirectoryInfo lockDir, string lockName)
		{
			_lockDir = lockDir;
			_lockFile = new FileInfo(Path.Combine(lockDir.FullName, lockName));
		}

		/// <summary>
		/// Attempts to obtain exclusive access and immediately return
		/// upon success or failure.
		/// </summary>
		/// <returns>true if exclusive access is obtained</returns>
		public override bool Obtain()
		{
			// Ensure that lockDir exists and is a directory:
			if (!_lockDir.Exists)
			{
				_lockDir.Create();
			}
			try
			{
				_lockFile.Create();
			}
			catch (IOException)
			{
				return false;
			}

			return true;
		}

		/// <summary>
		/// Releases exclusive access.
		/// </summary>
		public override void Release()
		{
			if (!_lockFile.Exists)
				throw new LockReleaseFailedException("failed to delete " + _lockFile);
			try
			{
				_lockFile.Delete();
			}
			catch (IOException e)
			{
				throw new LockReleaseFailedException("failed to delete " + _lockFile, e);
			}
		}

		/// <summary>
		/// Returns true if the resource is currently locked.  Note that one must
		/// still call <see cref="ILock.Obtain()"/> before using the resource.
		/// </summary>
		/// <returns></returns>
		public override bool IsLocked()
		{
			return _lockFile.Exists;
		}
		public override string ToString()
		{
			return "SimpleFSLock@" + _lockFile;
		}
	}
}